`timescale 1ns/1ns
`define DATA_WIDTH 256

module MLcozScalar(input clk,
				   input rst_n,
				   input enable,
				   input [`DATA_WIDTH-1:0] k,//验签KG是k1，KP是k2；签名是randomk，密钥交换是dA；
				   input MM_end_flag,
				   input INV_end_flag,
				   input error,
				   output reg [21:0] r_sel,
				   output reg [7:0] M_sel_a,
				   output reg [7:0] M_sel_b,
				   output reg [7:0] A_sel_a,
				   output reg [7:0] A_sel_b,
				   output reg [1:0] I_sel,
				   output reg MM_enable,
				   output reg INV_enable,
				   output reg func,
				   output reg end_flag
				  );

reg [7:0] count;

reg dblu_enable;
wire [21:0] dblu_r_sel;
wire [7:0] dblu_M_sel_a,dblu_M_sel_b,dblu_A_sel_a,dblu_A_sel_b;
wire dblu_endflag;
wire dblu_MM_enable,dblu_func;

reg zacau_enable;
wire [21:0] zacau_r_sel;
wire [7:0] zacau_M_sel_a,zacau_M_sel_b,zacau_A_sel_a,zacau_A_sel_b;
wire zacau_endflag;
wire zacau_MM_enable,zacau_func;

reg zaddc_enable;
wire [21:0] zaddc_r_sel;
wire [7:0] zaddc_M_sel_a,zaddc_M_sel_b,zaddc_A_sel_a,zaddc_A_sel_b;
wire zaddc_endflag;
wire zaddc_MM_enable,zaddc_func;

reg zaddu_enable;
wire [21:0] zaddu_r_sel;
wire [7:0] zaddu_M_sel_a,zaddu_M_sel_b,zaddu_A_sel_a,zaddu_A_sel_b;
wire zaddu_endflag;
wire zaddu_MM_enable,zaddu_func;


reg [21:0] scalar_r_sel;
reg [7:0] scalar_M_sel_a,scalar_M_sel_b,scalar_A_sel_a,scalar_A_sel_b;
reg scalar_MM_enable,scalar_func;

reg [20:0] state,next_state;

parameter IDLE = 21'b0_0000_0000_0000_0000_0001,
		  CHO_K= 21'b0_0000_0000_0000_0000_0011,
		  DBLU = 21'b0_0000_0000_0000_0000_0010,
		  EXCH = 21'b0_0000_0000_0000_0000_0100,
		  CSUM1= 21'b0_0000_0000_0000_0000_1000,
		  CSUM2= 21'b0_0000_0000_0000_0001_0000,
		  STEP1= 21'b0_0000_0000_0000_0010_0000,
		  STEP2= 21'b0_0000_0000_0000_0100_0000,
		  ZACAU= 21'b0_0000_0000_0000_1000_0000,
		  STEP3= 21'b0_0000_0000_0001_0000_0000,
		  ZADDC= 21'b0_0000_0000_0010_0000_0000,
		  REG  = 21'b0_0000_0000_0100_0000_0000,
		  ZSUM1= 21'b0_0000_0000_1000_0000_0000,
		  ZSUM2= 21'b0_0000_0001_0000_0000_0000,
		  ZSUM3= 21'b0_0000_0010_0000_0000_0000,
		  ZADDU= 21'b0_0000_0100_0000_0000_0000,
		  INV  = 21'b0_0000_1000_0000_0000_0000,
		  RSUM1= 21'b0_0001_0000_0000_0000_0000,
		  RSUM2= 21'b0_0010_0000_0000_0000_0000,
		  RSUM3= 21'b0_0100_0000_0000_0000_0000,
		  RSUM4= 21'b0_1000_0000_0000_0000_0000,
		  RSUM5= 21'b1_0000_0000_0000_0000_0000,
		  FINAL= 21'b1_0000_0000_0000_0000_0001;
		  
always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		state <= IDLE;
	end
	else if(error)
	begin
		state <= IDLE;
	end
	else
	begin
		state <= next_state;
	end
end

always @(*)
begin
	case(state)
	IDLE   :
			if(enable)
				next_state = CHO_K;
			else
				next_state = IDLE;
	CHO_K  :
			if(k==256'h1)
				next_state = FINAL;
			else
				next_state = DBLU;
	DBLU   :
			if(dblu_endflag)
				next_state = EXCH;
			else
				next_state = DBLU;
	EXCH   :
				next_state = CSUM1;
	CSUM1  :
				next_state = CSUM2;
	CSUM2  :
			if(MM_end_flag)
				next_state = STEP1;
			else
				next_state = CSUM2;
	STEP1  :
			if(k[count] == 1'b1)
				next_state = STEP2;
			else
				next_state = STEP1;
	STEP2  :
				
				next_state = ZACAU;
	ZACAU  :
			if((zacau_endflag == 1'b1) & (count != 1))
				next_state = STEP2;
			else if((zacau_endflag == 1'b1) & (count == 1'b1))
				next_state = STEP3;
			else
				next_state = ZACAU;
	STEP3  :
				next_state = ZADDC;
	ZADDC  :
			if(zaddc_endflag)
				next_state = REG;
			else
				next_state = ZADDC;
	REG    :
				next_state = ZSUM1;
	ZSUM1  :
			if(MM_end_flag)
				next_state = ZSUM2;
			else
				next_state = ZSUM1;
	ZSUM2  :
			if(MM_end_flag)
				next_state = ZSUM3;
			else
				next_state = ZSUM2;
	ZSUM3  :
			if(MM_end_flag)
				next_state = ZADDU;
			else
				next_state = ZSUM3;
	ZADDU  :
			if(zaddu_endflag)
				next_state = INV;
			else
				next_state = ZADDU;
	INV    :
			if(INV_end_flag)
				next_state = RSUM1;
			else
				next_state = INV;
	RSUM1  :
			if(MM_end_flag)
				next_state = RSUM2;
			else
				next_state = RSUM1;
	RSUM2  :
			if(MM_end_flag)
				next_state = RSUM3;
			else
				next_state = RSUM2;
	RSUM3  :
			if(MM_end_flag)
				next_state = RSUM4;
			else
				next_state = RSUM3;
	RSUM4  :
			if(MM_end_flag)
				next_state = RSUM5;
			else
				next_state = RSUM4;
	RSUM5  :
			if(MM_end_flag)
				next_state = IDLE;
			else
				next_state = RSUM5;
	FINAL : 	next_state = IDLE;
	default:	next_state = IDLE;
	endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		count <= 8'd255;
	end
	else if(enable)
	begin
		count <= 8'd255;
	end
	else if((state == STEP1) | ((state == ZACAU) & (zacau_endflag)))
	begin
		count <= count - 1'b1;
	end
	else
	begin
		count <= count;
	end
end

always @(*)
begin
		case(state)
		EXCH:
						scalar_r_sel = 22'b000_00_011_011_000_111_111_00;
		CSUM1:
						scalar_r_sel = 22'b000_00_000_000_001_000_000_00;
		CSUM2:
					if(MM_end_flag)
						scalar_r_sel = 22'b000_00_000_000_010_000_000_00;
					else
						scalar_r_sel = 22'b0;
		STEP2:
				if((k[count] ^ k[count+1]) ==1'b1)
						scalar_r_sel = 22'b000_00_011_011_000_111_111_00;
				else
						scalar_r_sel = 22'b0;
		STEP3: 
				if((k[0] ^ k[1]) == 1'b1)
						scalar_r_sel = 22'b000_00_011_011_000_111_111_00;
				else
						scalar_r_sel = 22'b0;
		REG:
						scalar_r_sel = 22'b000_11_000_000_011_000_000_00;
		ZSUM1:	
					if(MM_end_flag)
						scalar_r_sel = 22'b010_01_000_000_000_000_000_00;
					else
						scalar_r_sel = 22'b000_00_000_000_000_000_000_00;
		ZSUM2:
						scalar_r_sel = 22'b000_00_000_000_010_000_000_00;
		ZSUM3:
						scalar_r_sel = 22'b000_00_000_000_010_000_000_00;
		INV  :      if(INV_end_flag)
						scalar_r_sel = 22'b000_00_000_000_111_000_000_00;
					else
						scalar_r_sel = 22'b0;
		RSUM1:
					if(MM_end_flag)
						scalar_r_sel = 22'b010_00_000_000_000_000_000_00;
					else
						scalar_r_sel = 22'b0;
		RSUM2:
					if(MM_end_flag)
						scalar_r_sel = 22'b000_00_000_000_010_000_000_00;
					else
						scalar_r_sel = 22'b0;
		RSUM3:
					if(MM_end_flag)
						scalar_r_sel = 22'b010_00_000_000_000_000_000_00;
					else
						scalar_r_sel = 22'b0;
		RSUM4:
					if(MM_end_flag)
						scalar_r_sel = 22'b000_00_000_000_010_000_000_00;
					else
						scalar_r_sel = 22'b0;
		RSUM5:
					if(MM_end_flag)
						scalar_r_sel = 22'b010_00_000_000_000_000_000_00;
					else
						scalar_r_sel = 22'b0;
		default:
						scalar_r_sel = 22'b0;
		endcase
end

always @(*)
begin
		case(state)
		CSUM1:
		begin
				scalar_M_sel_a = 8'b0;
				scalar_M_sel_b = 8'b0;
				scalar_A_sel_a = 8'b00010000;//t4
				scalar_A_sel_b = 8'b00000010;//t1
		end
		CSUM2:
		begin
				scalar_M_sel_a = 8'b00001000;//t3
				scalar_M_sel_b = 8'b00001000;//t3
				scalar_A_sel_a = 8'b0;
				scalar_A_sel_b = 8'b0;
		end
		ZSUM1:
		begin
				if(k[0] == 1'b1)
				begin
				scalar_M_sel_a = 8'b01000000;//t6
				scalar_M_sel_b = 8'b00010000;//t4
				scalar_A_sel_a = 8'b00000010;//t1
				scalar_A_sel_b = 8'b00010000;//t4
				end
				else
				begin
				scalar_M_sel_a = 8'b01000000;//t6
				scalar_M_sel_b = 8'b00010000;//t4
				scalar_A_sel_a = 8'b00010000;//t4
				scalar_A_sel_b = 8'b00000010;//t1
				end
		end
		ZSUM2:
		begin
				scalar_M_sel_a = 8'b00001000;//t3
				scalar_M_sel_b = 8'b01000000;//t6
				scalar_A_sel_a = 8'b0;
				scalar_A_sel_b = 8'b0;
		end
		ZSUM3:
		begin
				scalar_M_sel_a = 8'b00001000;//t3
				scalar_M_sel_b = 8'b00100000;//t5
				scalar_A_sel_a = 8'b0;
				scalar_A_sel_b = 8'b0;
		end
		RSUM1:
		begin
				scalar_M_sel_a = 8'b10000000;//t7
				scalar_M_sel_b = 8'b00001000;//t3
				scalar_A_sel_a = 8'b0;
				scalar_A_sel_b = 8'b0;
		end
		RSUM2:
		begin
				scalar_M_sel_a = 8'b10000000;//t7
				scalar_M_sel_b = 8'b10000000;//t7
				scalar_A_sel_a = 8'b0;
				scalar_A_sel_b = 8'b0;
		end
		RSUM3:
		begin
				scalar_M_sel_a = 8'b10000000;//t7
				scalar_M_sel_b = 8'b00001000;//t3
				scalar_A_sel_a = 8'b0;
				scalar_A_sel_b = 8'b0;
		end
		RSUM4:
		begin
				if(k[0] == 1'b1)
				begin
				scalar_M_sel_a = 8'b00000010;//t1
				scalar_M_sel_b = 8'b00001000;//t3
				scalar_A_sel_a = 8'b0;
				scalar_A_sel_b = 8'b0;
				end
				else
				begin
				scalar_M_sel_a = 8'b00010000;//t4
				scalar_M_sel_b = 8'b00001000;//t3
				scalar_A_sel_a = 8'b0;
				scalar_A_sel_b = 8'b0;				
				end
		end
		RSUM5:
		begin
				if(k[0] == 1'b1)
				begin
				scalar_M_sel_a = 8'b00000100;//t2
				scalar_M_sel_b = 8'b10000000;//t7
				scalar_A_sel_a = 8'b0;
				scalar_A_sel_b = 8'b0;
				end
				else
				begin
				scalar_M_sel_a = 8'b00100000;//t5
				scalar_M_sel_b = 8'b10000000;//t7
				scalar_A_sel_a = 8'b0;
				scalar_A_sel_b = 8'b0;				
				end
		end
		default:
		begin
				scalar_M_sel_a = 8'b0;
				scalar_M_sel_b = 8'b0;
				scalar_A_sel_a = 8'b0;
				scalar_A_sel_b = 8'b0;
		end
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		scalar_MM_enable <= 1'b0;
	end
	else
	begin
		case(next_state)
		CSUM2:
				if(state == CSUM1)
				scalar_MM_enable <= 1'b1;
				else
				scalar_MM_enable <= 1'b0;
		ZSUM1:
				if(state == REG)
				scalar_MM_enable <= 1'b1;
				else
				scalar_MM_enable <= 1'b0;
		ZSUM2:
				if(state == ZSUM1)
				scalar_MM_enable <= 1'b1;
				else
				scalar_MM_enable <= 1'b0;
		ZSUM3:
				if(state == ZSUM2)
				scalar_MM_enable <= 1'b1;
				else
				scalar_MM_enable <= 1'b0;
		RSUM1:
				if(state == INV)
				scalar_MM_enable <= 1'b1;
				else
				scalar_MM_enable <= 1'b0;
		RSUM2:
				if(state == RSUM1)
				scalar_MM_enable <= 1'b1;
				else
				scalar_MM_enable <= 1'b0;
		RSUM3:
				if(state == RSUM2)
				scalar_MM_enable <= 1'b1;
				else
				scalar_MM_enable <= 1'b0;
		RSUM4:
				if(state == RSUM3)
				scalar_MM_enable <= 1'b1;
				else
				scalar_MM_enable <= 1'b0;
		RSUM5:
				if(state == RSUM4)
				scalar_MM_enable <= 1'b1;
				else
				scalar_MM_enable <= 1'b0;
		default:
				scalar_MM_enable <= 1'b0;
		endcase
	end
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		scalar_func <= 1'b0;
	end
	else 
	begin
		case(next_state)
		CSUM1:
				scalar_func <= 1'b1;
		ZSUM1:
				scalar_func <= 1'b1;
		default:
				scalar_func <= 1'b0;
		endcase
	end
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		dblu_enable <= 1'b0;
	end
	else if((state == CHO_K) & (next_state == DBLU))
	begin
		dblu_enable <= 1'b1;
	end
	else
	begin
		dblu_enable <= 1'b0;
	end
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		zacau_enable <= 1'b0;
	end
	else if((state == STEP2) & (next_state == ZACAU))
	begin
		zacau_enable <= 1'b1;
	end
	else
	begin
		zacau_enable <= 1'b0;
	end
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		zaddc_enable <= 1'b0;
	end
	else if((state == STEP3) & (next_state == ZADDC))
	begin
		zaddc_enable <= 1'b1;
	end
	else
	begin
		zaddc_enable <= 1'b0;
	end
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		zaddu_enable <= 1'b0;
	end
	else if((state == ZSUM3) & (MM_end_flag))
	begin
		zaddu_enable <= 1'b1;
	end
	else
	begin
		zaddu_enable <= 1'b0;
	end
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		end_flag <= 1'b0;
	end
	else if((state == RSUM5) & MM_end_flag)
	begin
		end_flag <= 1'b1;
	end
	//else if((state == CHO_K) && (next_state == FINAL))
	else if((state == CHO_K) && (k==256'h1))
	begin
		end_flag <= 1'b1;
	end
	else
	begin
		end_flag <= 1'b0;
	end
end

DBLU_coz dblu_coz(.clk(clk),.rst_n(rst_n),.enable(dblu_enable),.error(error),.MM_end_flag(MM_end_flag),.MM_enable(dblu_MM_enable),.func(dblu_func),.r_sel(dblu_r_sel),.M_sel_a(dblu_M_sel_a),.M_sel_b(dblu_M_sel_b),.A_sel_a(dblu_A_sel_a),.A_sel_b(dblu_A_sel_b),.end_flag(dblu_endflag));

ZACAU_coz zacau_coz(.clk(clk),.rst_n(rst_n),.enable(zacau_enable),.MM_end_flag(MM_end_flag),.MM_enable(zacau_MM_enable),.func(zacau_func),.r_sel(zacau_r_sel),.M_sel_a(zacau_M_sel_a),.M_sel_b(zacau_M_sel_b),.A_sel_a(zacau_A_sel_a),.A_sel_b(zacau_A_sel_b),.end_flag(zacau_endflag));

ZADDC_coz zaddc_coz(.clk(clk),.rst_n(rst_n),.enable(zaddc_enable),.MM_end_flag(MM_end_flag),.MM_enable(zaddc_MM_enable),.func(zaddc_func),.r_sel(zaddc_r_sel),.M_sel_a(zaddc_M_sel_a),.M_sel_b(zaddc_M_sel_b),.A_sel_a(zaddc_A_sel_a),.A_sel_b(zaddc_A_sel_b),.end_flag(zaddc_endflag));

ZADDU_coz zaddu_coz(.clk(clk),.rst_n(rst_n),.enable(zaddu_enable),.MM_end_flag(MM_end_flag),.MM_enable(zaddu_MM_enable),.func(zaddu_func),.r_sel(zaddu_r_sel),.M_sel_a(zaddu_M_sel_a),.M_sel_b(zaddu_M_sel_b),.A_sel_a(zaddu_A_sel_a),.A_sel_b(zaddu_A_sel_b),.end_flag(zaddu_endflag));

always @(*)
begin
	case(state)
	IDLE   : r_sel = 22'b0;
	CHO_K  : if(k==256'h1)
			 r_sel = 22'b100_00_000_000_011_000_000_00;
			 else
			 r_sel = 22'b0;
	DBLU   : r_sel = dblu_r_sel;
	EXCH   : r_sel = scalar_r_sel;
	CSUM1  : r_sel = scalar_r_sel;
	CSUM2  : r_sel = scalar_r_sel;
	STEP1  : r_sel = 22'b0;
	STEP2  : r_sel = scalar_r_sel;
	ZACAU  : r_sel = zacau_r_sel;
	STEP3  : r_sel = scalar_r_sel;
	ZADDC  : r_sel = zaddc_r_sel;
	REG    : r_sel = scalar_r_sel;
	ZSUM1  : r_sel = scalar_r_sel;
	ZSUM2  : r_sel = scalar_r_sel;
	ZSUM3  : r_sel = scalar_r_sel;
	ZADDU  : r_sel = zaddu_r_sel;
	INV    : r_sel = scalar_r_sel;
	RSUM1  : r_sel = scalar_r_sel;
	RSUM2  : r_sel = scalar_r_sel;
	RSUM3  : r_sel = scalar_r_sel;
	RSUM4  : r_sel = scalar_r_sel;
	RSUM5  : r_sel = scalar_r_sel;
	FINAL  : r_sel = 22'b0;
	default: r_sel = 22'b0;
	endcase
end

always @(*)
begin
	case(state)
	IDLE   : 
	begin
			M_sel_a = 8'b0;
			M_sel_b = 8'b0;
			A_sel_a = 8'b0;
			A_sel_b = 8'b0;
	end
	DBLU   : 
	begin
			M_sel_a = dblu_M_sel_a;
			M_sel_b = dblu_M_sel_b;
			A_sel_a = dblu_A_sel_a;
			A_sel_b = dblu_A_sel_b;
	end
	EXCH   : 
	begin
			M_sel_a = scalar_M_sel_a;
			M_sel_b = scalar_M_sel_b;
			A_sel_a = scalar_A_sel_a;
			A_sel_b = scalar_A_sel_b;		
	end
	CSUM1  : 
	begin
			M_sel_a = scalar_M_sel_a;
			M_sel_b = scalar_M_sel_b;
			A_sel_a = scalar_A_sel_a;
			A_sel_b = scalar_A_sel_b;
	end
	CSUM2  : 
	begin
			M_sel_a = scalar_M_sel_a;
			M_sel_b = scalar_M_sel_b;
			A_sel_a = scalar_A_sel_a;
			A_sel_b = scalar_A_sel_b;
	end
	STEP1  : 
	begin
			M_sel_a = 8'b0;
			M_sel_b = 8'b0;
			A_sel_a = 8'b0;
			A_sel_b = 8'b0;
    end			
	STEP2  :
	begin
			M_sel_a = 8'b0;
			M_sel_b = 8'b0;
			A_sel_a = 8'b0;
			A_sel_b = 8'b0;	
    end			
	ZACAU  :
	begin
			M_sel_a = zacau_M_sel_a;
			M_sel_b = zacau_M_sel_b;
			A_sel_a = zacau_A_sel_a;
			A_sel_b = zacau_A_sel_b;	
	end
	STEP3  :
	begin
			M_sel_a = 8'b0;
			M_sel_b = 8'b0;
			A_sel_a = 8'b0;
			A_sel_b = 8'b0;		
	end		
	ZADDC  :
	begin
			M_sel_a = zaddc_M_sel_a;
			M_sel_b = zaddc_M_sel_b;
			A_sel_a = zaddc_A_sel_a;
			A_sel_b = zaddc_A_sel_b;		
    end			
	REG    :
	begin
			M_sel_a = 8'b0;
			M_sel_b = 8'b0;
			A_sel_a = 8'b0;
			A_sel_b = 8'b0;		
    end			
	ZSUM1  :
	begin
			M_sel_a = scalar_M_sel_a;
			M_sel_b = scalar_M_sel_b;
			A_sel_a = scalar_A_sel_a;
			A_sel_b = scalar_A_sel_b;		
    end			
	ZSUM2  :
	begin
			M_sel_a = scalar_M_sel_a;
			M_sel_b = scalar_M_sel_b;
			A_sel_a = scalar_A_sel_a;
			A_sel_b = scalar_A_sel_b;
    end			
	ZSUM3  :
	begin
			M_sel_a = scalar_M_sel_a;
			M_sel_b = scalar_M_sel_b;
			A_sel_a = scalar_A_sel_a;
			A_sel_b = scalar_A_sel_b;
    end			
	ZADDU  :
	begin
			M_sel_a = zaddu_M_sel_a;
			M_sel_b = zaddu_M_sel_b;
			A_sel_a = zaddu_A_sel_a;
			A_sel_b = zaddu_A_sel_b;	
    end
	INV    :
	begin
			M_sel_a = scalar_M_sel_a;
			M_sel_b = scalar_M_sel_b;
			A_sel_a = scalar_A_sel_a;
			A_sel_b = scalar_A_sel_b;
    end			
	RSUM1  :
	begin
			M_sel_a = scalar_M_sel_a;
			M_sel_b = scalar_M_sel_b;
			A_sel_a = scalar_A_sel_a;
			A_sel_b = scalar_A_sel_b;
    end
	RSUM2  :
	begin
			M_sel_a = scalar_M_sel_a;
			M_sel_b = scalar_M_sel_b;
			A_sel_a = scalar_A_sel_a;
			A_sel_b = scalar_A_sel_b;
    end	
	RSUM3  :
	begin
			M_sel_a = scalar_M_sel_a;
			M_sel_b = scalar_M_sel_b;
			A_sel_a = scalar_A_sel_a;
			A_sel_b = scalar_A_sel_b;
    end	
	RSUM4  :
	begin
			M_sel_a = scalar_M_sel_a;
			M_sel_b = scalar_M_sel_b;
			A_sel_a = scalar_A_sel_a;
			A_sel_b = scalar_A_sel_b;
    end	
	RSUM5  :
	begin
			M_sel_a = scalar_M_sel_a;
			M_sel_b = scalar_M_sel_b;
			A_sel_a = scalar_A_sel_a;
			A_sel_b = scalar_A_sel_b;
    end		
	default:
	begin
			M_sel_a = 8'b0;
			M_sel_b = 8'b0;
			A_sel_a = 8'b0;
			A_sel_b = 8'b0;
	end
	endcase
end

always @(*)
begin
	case(state)
	IDLE   : MM_enable = 1'b0;
	DBLU   : MM_enable = dblu_MM_enable;
	EXCH   : MM_enable = 1'b0;
	CSUM1  : MM_enable = scalar_MM_enable;
	CSUM2  : MM_enable = scalar_MM_enable;
	STEP1  : MM_enable = 1'b0;
	STEP2  : MM_enable = 1'b0;
	ZACAU  : MM_enable = zacau_MM_enable;
	STEP3  : MM_enable = 1'b0;
	ZADDC  : MM_enable = zaddc_MM_enable;
	REG    : MM_enable = 1'b0;
	ZSUM1  : MM_enable = scalar_MM_enable;
	ZSUM2  : MM_enable = scalar_MM_enable;
	ZSUM3  : MM_enable = scalar_MM_enable;
	ZADDU  : MM_enable = zaddu_MM_enable;
	INV    : MM_enable = 1'b0;
	RSUM1  : MM_enable = scalar_MM_enable;
	RSUM2  : MM_enable = scalar_MM_enable;
	RSUM3  : MM_enable = scalar_MM_enable;
	RSUM4  : MM_enable = scalar_MM_enable;
	RSUM5  : MM_enable = scalar_MM_enable;
	default: MM_enable = 1'b0;
	endcase
end

always @(*)
begin
	case(state)
	IDLE   : func = 1'b0;
	DBLU   : func = dblu_func;
	EXCH   : func = 1'b0;
	CSUM1  : func = scalar_func;
	CSUM2  : func = scalar_func;
	STEP1  : func = 1'b0;
	STEP2  : func = 1'b0;
	ZACAU  : func = zacau_func;
	STEP3  : func = 1'b0;
	ZADDC  : func = zaddc_func;
	REG    : func = 1'b0;
	ZSUM1  : func = scalar_func;
	ZSUM2  : func = scalar_func;
	ZSUM3  : func = scalar_func;
	ZADDU  : func = zaddu_func;
	INV    : func = 1'b0;
	RSUM1  : func = 1'b0;
	RSUM2  : func = 1'b0;
	RSUM3  : func = 1'b0;
	RSUM4  : func = 1'b0;
	RSUM5  : func = 1'b0;
	default: func = 1'b0;
	endcase
end

always @(*)
begin
	case(state)
	INV : I_sel = 2'b01;
	default : I_sel = 2'b00;
	endcase
end	
	
always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		INV_enable <= 1'b0;
	end
	else if((state == ZADDU) & (zaddu_endflag))
	begin
		INV_enable <= 1'b1;
	end
	else
	begin
		INV_enable <= 1'b0;
	end
end

endmodule